package com.yang.bean.xml;

import com.yang.bean.beanDefinition.BeanDefinition;
import com.yang.bean.beanDefinition.PropertyValue;
import com.yang.bean.beanDefinition.RuntimeBeanReference;
import com.yang.bean.beanDefinition.TypeStringValue;
import com.yang.bean.beanfactory.registry.BeanDefinitionRegistry;
import com.yang.bean.util.ReflectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Element;

import javax.lang.model.element.VariableElement;
import java.util.List;

/**
 * @Description: 把XML解析出来的BeanDefinition注册到map中
 * @author: Yang Qiang
 * @create: 2021-11-08 21:23
 */
public class DefaultBeanDefinitionDocumentReader {

    // BeanDefinition的Map
    private BeanDefinitionRegistry beanDefinitionRegistry;

    public DefaultBeanDefinitionDocumentReader(BeanDefinitionRegistry beanDefinitionRegistry) {
        this.beanDefinitionRegistry = beanDefinitionRegistry;
    }

    /**
     * 通过Element注册
     * @param rootElement
     */
    public void registryBeanDefinitions(Element rootElement) {

        List<Element> elements = rootElement.elements();

        for (Element element : elements) {
            // 获取标签
            String name = element.getName();
            if ("bean".equals(name)){
                // 解析默认标签
                parserDefaultElement(element);
            }else{
                // 解析自定义标签
                parserCustomElement(element);
            }
        }

    }

    private void parserCustomElement(Element element) {
        try {
            if (element == null){
                return;
            }
            // 获取可以
            String id = element.attributeValue("id");
            String name = element.attributeValue("name");
            // 获取对应的属性
            String className = element.attributeValue("class");
            Class aClass = Class.forName(className);
            // 获取是否单例
            String scope = element.attributeValue("scope");
            if (StringUtils.isBlank(scope)){
                scope = "singleton";
            }


            String beanName = StringUtils.isBlank(id) ? name : id;
            if (StringUtils.isBlank(beanName)){
                beanName = aClass.getSimpleName();
            }

            // 创建BeanDefinition
            BeanDefinition beanDefinition = new BeanDefinition(beanName, className);
            beanDefinition.setScope(scope);

            // 设置property标签
            List<Element> elements = element.elements();
            for (Element propertyElement : elements) {
                parsePropertyElement(beanDefinition, propertyElement);
            }

            beanDefinitionRegistry.registryBeanDefinition(beanName, beanDefinition);

        } catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 解析property标签, 然后为BeanDefinition对象set进去
     * @param beanDefinition
     * @param propertyElement
     */
    private void parsePropertyElement(BeanDefinition beanDefinition, Element propertyElement) {

        if (beanDefinition == null || propertyElement == null){
            return;
        }

        // 获取name属性
        String name = propertyElement.attributeValue("name");
        // 获取value值或者ref值
        String value = propertyElement.attributeValue("value");
        // 获取ref属性
        String ref = propertyElement.attributeValue("ref");
        if (StringUtils.isBlank(value) && StringUtils.isBlank(ref)){
            System.out.println("value 和 ref 不能同时为null");
            return;
        }
        if (StringUtils.isNotBlank(value)){
            // 处理基本类型
            TypeStringValue typeStringValue = new TypeStringValue(value);
            // 获取对象属性的相应类型
            Class<?> targetType = ReflectionUtils.getTypeByFieldName(beanDefinition.getClassName(), name);
            typeStringValue.setTargetType(targetType);
            PropertyValue propertyValue = new PropertyValue(name, typeStringValue);
            beanDefinition.addProperty(propertyValue);
        }else if (StringUtils.isNotBlank(ref)){
            // 处理ref属性
            RuntimeBeanReference reference = new RuntimeBeanReference(ref);
            PropertyValue propertyValue = new PropertyValue(name, reference);
            beanDefinition.addProperty(propertyValue);
        }
    }

    private void parserDefaultElement(Element element) {
    }
}
